require 'net/http'
require 'rexml/document'

class ItemsController < ApplicationController
  before_filter :require_officer, :except => [ :index, :show ]

  def index
    @page_description = "Items"
    @items = Item.paginate(:page => params[:page], :order => :name)

    # we should probably use session[:item] instead
    if flash[:item]
      @item = flash[:item]
      flash[:item] = @item
      @loot_records = Loot.find(:all, :conditions => { :item_id => @item.id })
    end

    begin
      if (@item.nil? == false) and (@item.wowid > 0)
        xml = fetch_xml(@item.wowid)
        @itemdisplay = extract_field_from_xml(xml, "htmlTooltip")
      end
    rescue Exception => e
      @itemdisplay = nil
    end

    if is_officer?
      if @item.nil?
        @item = Item.new
        flash[:item] = @item
      end
      if @item.new_record?
        @form_method = { :method => :post }
        @form_url = { :action => :create }
      else
        @form_method = { :method => :put }
        @form_url = { :action => :update, :id => @item.id }
      end
    end
  end

  def create
    # the only way to get here should be through index, which has set flash[:item]
    item = flash[:item]
    item.attributes = params[:item]
    if params[:sync]
      update
    else
      if item.save
        flash[:notice] = "#{item.name} added to database."
      else
        flash[:notice] = "Failed to save #{item.name} to the database."
      end
      redirect_to(:back)
    end
  end

  def show
    flash[:notice] = flash[:notice]
    begin
      item = Item.find(params[:id])
      flash[:item] = item
    rescue ActiveRecord::RecordNotFound => ex
      flash[:notice] = "No item with ID #{params[:id]}.\n"
    end
    redirect_to(:action => :index)
  end
  alias edit show

  def update
    if params[:sync]
      item = flash[:item]
      if params[:item]
        item.attributes = params[:item]
      end
      sync(item)
      flash[:item] = item
      redirect_to(:action => :index)
    else
      item = Item.find(params[:id])
      if item.update_attributes(params[:item])
        flash[:notice] = "#{item.name} updated."
      end
      if params[:update_history]
        loot_records = Loot.find(:all, :conditions => { :item_id => item.id })
        loot_records.each { |record|
          record.price = item.default_price
          record.save
        }
      end
      expire_fragment("characters/dkp_table")
      Reward.update_total_number_of_shares
      redirect_to(:action => :show, :id => params[:id])
    end
  end

  private
  def sync(item)
    begin
      xml = fetch_xml(item.wowid)
      extracted_name = extract_field_from_xml(xml, "name")
    rescue Exception => e
      flash[:notice] = "Failed to sync name.\n"
    else
      item.name = extracted_name
    end
  end

  def fetch_xml(wowid)
    response = nil
    begin
      uri = URI.parse("http://www.wowhead.com/?item=#{wowid}&xml")
      http = Net::HTTP.new(uri.host)
      http.open_timeout = 20
      http.read_timeout = 30
      response = http.get(uri.request_uri).body
    rescue Exception => e
      raise "Couldn't fetch XML for WoW item #{wowid}."
      response = nil
    end
    return response
  end

  def extract_field_from_xml(xmldata, field)
    match = nil
    begin
      xml = REXML::Document.new(xmldata)
      field = xml.root().find_first_recursive { |e| e.name == field }
      if field
        match = field.cdatas[0].value
      end
    rescue Exception => e
      raise "Failed to extract field #{field}."
      match = nil
    end
    return match
  end

end
